class Kvue extends EventTarget{
  constructor(opts) {
    super();
    this.$options = opts;
  
    this.compile();
    this.observer();
  }
  
  // 编译器
  compile() {
    let $el = document.querySelector(this.$options.el);
    this.compileNodes($el);
  }

  // 节点编译器
  compileNodes($el) {
    let nodes = $el.childNodes;
    nodes.forEach(node => {
      if (node.nodeType === 1) {
        // 标签
        let attrs = node.attributes;
        [...attrs].forEach(attr => {
          let attrName = attr.name;
          let attrValue = attr.value;

          if (attrName.indexOf('v-') === 0) {
            let lastName = attrName.substr(2);
            if (lastName === 'html') {
              node.innerHTML = this.$options.data[attrValue];
            } else if (lastName === 'model') {
              node.value = this.$options.data[attrValue];
              node.addEventListener('input', e => {
                this.$options.data[attrValue] = e.target.value;
              })
            }
          }
        })

        this.compileNodes(node);
      } else if (node.nodeType === 3) {
        // 文本节点
        let reg = /\{\{\s*(\S+)\s*\}\}/g;
        if (reg.test(node.textContent)) {
          let $1 = RegExp.$1;
          node.textContent = node.textContent.replace(reg, this.$options.data[$1]);
          this.addEventListener($1, ({ detail }) => {
            let oldValue = this.$options.data[$1];
            node.textContent = node.textContent.replace(oldValue, detail);
          })
        }
      }
    })
  }

  // 观察者
  observer() {
    let data = this.$options.data;
    for (let key in data) {
      this.dataReact(data, key, data[key]);
    }
  }

  // 数据劫持
  dataReact(data, key, value) {
    let _this = this;
    Object.defineProperty(data, key, {
      configurable: true,
      enumerable: true,
      get() {
        return value;
      },
      set(newValue) {
        let event = new CustomEvent(key, {
          detail: newValue
        });
        _this.dispatchEvent(event);
        value = newValue;
      }
    })
  }
}